/**
 * QUANSHI.com Inc.
 * Copyright (c) 2016-2017 All Rights Reserved.
 */
package com.quanshi.scheduler.job.biz.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.github.pagehelper.PageHelper;
import com.quanshi.scheduler.core.base.Ret;
import com.quanshi.scheduler.core.biz.ExecutorBiz;
import com.quanshi.scheduler.core.biz.model.LogResult;
import com.quanshi.scheduler.core.rpc.netcom.jetty.NetComClientProxy;
import com.quanshi.scheduler.job.biz.model.req.TriggerLogReq;
import com.quanshi.scheduler.job.biz.service.BaseService;
import com.quanshi.scheduler.job.biz.service.TriggerLogService;
import com.quanshi.scheduler.job.dal.dao.TriggerLogMapper;
import com.quanshi.scheduler.job.dal.entity.TriggerLog;
import com.quanshi.scheduler.job.dal.entity.TriggerLogExample;
import com.quanshi.scheduler.job.dal.entity.TriggerLogExample.Criteria;

/**
 * 
 * @author yanxiang.huang 2017-07-11 10:30:25
 */
@Service
public class TriggerLogServiceImpl extends BaseService implements TriggerLogService
{

    @Resource
    private TriggerLogMapper mapper;

    @Override
    public void save( TriggerLog jobLog )
    {
        Assert.notNull( jobLog, "job log can't be null." );
        jobLog.setTriggerCode( 0 );
        jobLog.setHandleCode( 0 );
        mapper.insert( jobLog );
    }

    @Override
    public void update( TriggerLog jobLog )
    {
        Assert.notNull( jobLog, "job log can't be null." );
        TriggerLog oldLog = get( jobLog.getId() );
        if ( oldLog == null )
        {
            logger.info( "old job log can't found. id:{}.", jobLog.getId() );
            return;
        }
        mapper.updateByPrimaryKeySelective( jobLog );
    }

    @Override
    public TriggerLog get( Long jobLogId )
    {
        Assert.notNull( jobLogId, "job log id can't be null." );
        TriggerLog log = mapper.selectByPrimaryKey( jobLogId );
        return log;
    }

    @Override
    public long findAllCount()
    {
        TriggerLogExample query = new TriggerLogExample();
        return mapper.countByExample( query );
    }

    @Override
    public long findTrggingCount()
    {
        TriggerLogExample query = new TriggerLogExample();
        query.createCriteria().andTriggerCodeEqualTo( 0 ).andHandleCodeEqualTo( 0 );
        return mapper.countByExample( query );
    }

    @Override
    public long findRunningCount()
    {
        TriggerLogExample query = new TriggerLogExample();
        query.createCriteria().andTriggerCodeEqualTo( Ret.SUCCESS_CODE ).andHandleCodeEqualTo( 0 );
        return mapper.countByExample( query );
    }

    @Override
    public long findTriggerSucCount()
    {
        TriggerLogExample query = new TriggerLogExample();
        query.createCriteria().andTriggerCodeEqualTo( Ret.SUCCESS_CODE );
        return mapper.countByExample( query );
    }

    @Override
    public long findTriggerFailCount()
    {
        TriggerLogExample query = new TriggerLogExample();
        query.createCriteria().andTriggerCodeEqualTo( Ret.FAIL_CODE );
        return mapper.countByExample( query );
    }

    @Override
    public long findHandleSucCount()
    {
        TriggerLogExample query = new TriggerLogExample();
        query.createCriteria().andHandleCodeEqualTo( Ret.SUCCESS_CODE );
        return mapper.countByExample( query );
    }

    @Override
    public long findHandleFailCount()
    {
        TriggerLogExample query = new TriggerLogExample();
        query.createCriteria().andHandleCodeEqualTo( Ret.FAIL_CODE );
        return mapper.countByExample( query );
    }

    @Override
    public void deleteByJobId( long jobId )
    {
        TriggerLogExample query = new TriggerLogExample();
        query.createCriteria().andJobIdEqualTo( jobId );
        mapper.deleteByExample( query );
    }

    @Override
    public Map<String, Object> findDataPage( TriggerLogReq req )
    {
        Assert.notNull( req, "req can't be null." );
        TriggerLogExample query = createQuery( req );
        if ( req.getStart() >= 0 && req.getLength() > 0 )
        {
            PageHelper.offsetPage( req.getStart(), req.getLength() );
        }
        else
        {
            PageHelper.offsetPage( 0, 10 );
        }
        List<TriggerLog> datas = mapper.selectByExample( query );
        long total = mapper.countByExample( query );
        PageHelper.clearPage();
        Map<String, Object> maps = new HashMap<String, Object>();
        maps.put( "recordsTotal", total ); // 总记录数
        maps.put( "recordsFiltered", total ); // 过滤后的总记录数
        maps.put( "data", datas );
        return maps;
    }

    @Override
    public Ret<LogResult> catLog( String executorAddress, long triggerTime, long logId, int fromLineNum )
    {
        try
        {
            ExecutorBiz executorBiz = ( ExecutorBiz ) new NetComClientProxy( ExecutorBiz.class, executorAddress )
                    .getObject();
            Ret<LogResult> res = executorBiz.log( triggerTime, logId, fromLineNum );

            if ( res.getContent() != null && res.getContent().getFromLineNum() > res.getContent().getToLineNum() )
            {
                TriggerLog jobLog = get( logId );
                if ( jobLog.getHandleCode() > 0 )
                {
                    res.getContent().setEnd( true );
                }
            }
            return res;
        }
        catch ( Exception e )
        {
            logger.error( "", e );
            return new Ret<>( Ret.FAIL_CODE, e.getMessage() );
        }
    }

    @Override
    public Ret<?> killLog( TriggerLog log )
    {
        ExecutorBiz executorBiz = null;
        try
        {
            executorBiz = ( ExecutorBiz ) new NetComClientProxy( ExecutorBiz.class, log.getExecutorAddress() )
                    .getObject();
        }
        catch ( Exception e )
        {
            logger.error( "", e );
            return new Ret<String>( Ret.FAIL_CODE, e.getMessage() );
        }
        Ret<String> runResult = executorBiz.kill( log.getId() );

        if ( Ret.SUCCESS_CODE == runResult.getCode() )
        {
            log.setHandleCode( Ret.FAIL_CODE );
            log.setHandleMsg( "人为操作主动终止:" + (runResult.getMsg() != null ? runResult.getMsg() : "") );
            log.setHandleTime( new Date() );
            update( log );
            return new Ret<String>( runResult.getMsg() );
        }
        else
        {
            return new Ret<String>( Ret.FAIL_CODE, runResult.getMsg() );
        }
    }

    @Override
    public void clearLog( Long jobGroup, Long jobId, Date clearBeforeTime, int clearBeforeNum )
    {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("jobGroup", jobGroup);
        params.put("jobId", jobId);
        params.put("clearBeforeTime", clearBeforeTime);
        params.put("clearBeforeNum", clearBeforeNum);
        mapper.clearLog(params);
    }

    /**
     * 构建查询条件
     *
     * @param req
     * @return
     */
    private TriggerLogExample createQuery( TriggerLogReq req )
    {
        TriggerLogExample query = new TriggerLogExample();
        Criteria c = query.createCriteria();
        if ( req.getJobGroup() != null && req.getJobGroup() > 0 )
        {
            c.andJobGroupEqualTo( req.getJobGroup() );
        }
        if ( req.getJobId() != null && req.getJobId() > 0 )
        {
            c.andJobIdEqualTo( req.getJobId() );
        }
        if ( req.getDateStart() != null )
        {
            c.andTriggerTimeGreaterThanOrEqualTo( req.getDateStart() );
        }
        if ( req.getDateEnd() != null )
        {
            c.andTriggerTimeLessThanOrEqualTo( req.getDateEnd() );
        }
        return query;
    }
}
